#ifndef __BUOLA_GL_CUNIFORM_H__
#define __BUOLA_GL_CUNIFORM_H__

#include <buola/gl.h>

namespace buola { namespace gl {

class CUniform
{
public:
    CUniform()
        :   mID(-1)
    {}
    
    CUniform(GLint pID)
        :   mID(pID)
    {}

    CUniform(const CUniform &pRH)
        :   mID(pRH.mID)
    {}

    CUniform &operator=(const CUniform &pRH)
    {
        mID=pRH.mID;
        return *this;
    }

    void SetValue(const mat::CMat4d &pMatrix)
    {
        GLfloat lMatrix[16];
        for(int i=0;i<4;i++)
            for(int j=0;j<4;j++)
                lMatrix[j*4+i]=pMatrix(i,j);

        glUniformMatrix4fv(mID,1,false,lMatrix);
    }

    void SetValue(const mat::CMat34d &pMatrix)
    {
        GLfloat lMatrix[16];
        for(int j=0;j<4;j++)
            for(int i=0;i<3;i++)
                lMatrix[j*4+i]=pMatrix(i,j);
        lMatrix[3]=0;
        lMatrix[7]=0;
        lMatrix[11]=0;
        lMatrix[15]=1;

        glUniformMatrix4fv(mID,1,false,lMatrix);
    }

    void SetValue(const mat::CMat23d &pMatrix)
    {
        GLfloat lMatrix[6];
        for(int i=0;i<2;i++)
            for(int j=0;j<3;j++)
                lMatrix[i*3+j]=pMatrix(i,j);

        glUniformMatrix2x3fv(mID,1,false,lMatrix);
    }

    void SetValue(const std::vector<mat::CMat4d> &pMatrices)
    {
        if(pMatrices.empty()) return;
        GLfloat lMatrices[16*pMatrices.size()];
        for(int k=0;k<pMatrices.size();k++)
        {
            for(int i=0;i<4;i++)
                for(int j=0;j<4;j++)
                    lMatrices[k*16+j*4+i]=pMatrices[k](i,j);
        }

        glUniformMatrix4fv(mID,pMatrices.size(),false,lMatrices);
    }

    void SetValue(const std::vector<mat::CMat34d> &pMatrices)
    {
        if(pMatrices.empty()) return;
        GLfloat lMatrices[16*pMatrices.size()];
        for(int k=0;k<pMatrices.size();k++)
        {
            for(int i=0;i<3;i++)
                for(int j=0;j<4;j++)
                    lMatrices[k*16+j*4+i]=pMatrices[k](i,j);
            lMatrices[k*16+3]=0;
            lMatrices[k*16+7]=0;
            lMatrices[k*16+11]=0;
            lMatrices[k*16+15]=1;
        }

        glUniformMatrix4fv(mID,pMatrices.size(),false,lMatrices);
    }

    void SetValue(int pInt)
    {
        glUniform1i(mID,pInt);
    }

    void SetValue(float pFloat)
    {
        glUniform1f(mID,pFloat);
    }
    
    void SetValue(const CPoint_d &pPoint)
    {
        glUniform2f(mID,pPoint.x,pPoint.y);
    }
    
    void SetValue(const mat::CVec3f &pPoint)
    {
        glUniform3f(mID,pPoint.x(),pPoint.y(),pPoint.z());
    }
    
    void SetValue(const mat::CVec4f &pPoint)
    {
        glUniform4f(mID,pPoint.x(),pPoint.y(),pPoint.z(),pPoint.w());
    }
    
    void SetValue(const img::CColor &pColor)
    {
        glUniform4f(mID,pColor.r,pColor.g,pColor.b,pColor.a);
    }

    GLint GetID()      {   return mID; }

private:
    GLint mID;
};

/*namespace gl*/ } /*namespace buola*/ }

#endif
